#pragma once
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <cstring>

namespace My_Thread
{
    typedef void *(*thread_func)(void *);
    static size_t __ID = 0;
    class Thread
    {
    public:
        Thread()
            : _tid(0), _run(false), _detach(false), _name("thread id: " + std::to_string(__ID++))
        {
        }
        Thread(const Thread &cpy) = delete;
        Thread operator=(const Thread &cpy) = delete;
        ~Thread() = default;

        const char *GetName()
        {
            return _name.c_str();
        }

        pthread_t GetID()
        {
            return _tid;
        }

        bool IsRun()
        {
            return _run;
        }

        bool IsDecach()
        {
            return _detach;
        }

        bool Runing(thread_func func)
        {
            if (_run == false)
            {
                int pret = pthread_create(&_tid, NULL, func, (void *)GetName());
                if (pret != 0)
                {
                    return false;
                }
                _run = true;
                if (_detach == true)
                {
                    pthread_detach(_tid);
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        void Stop()
        {
            if (_run == true)
            {
                pthread_cancel(_tid);
                _run = false;
                _detach = false;
            }
        }

        void Detach()
        {
            if (_detach == false)
            {
                if (_run == true)
                {
                    int pthread_detach(_tid);
                    _detach = true;
                }
                else
                {
                    _detach = true;
                }
            }
        }

        void *Join()
        {
            if (_run == true && _detach == false)
            {
                pthread_join(_tid, &_join);
                _run = false;
                return _join;
            }
            else
            {
                return nullptr;
            }
        }

    private:
        pthread_t _tid;
        bool _run;
        bool _detach;
        std::string _name;
        void *_join = nullptr;
    };
}